package cate.common.table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.time.DateTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;

import java.lang.reflect.Field;
import java.util.Date;

@Slf4j
public abstract class ERow {
    @JsonIgnore
    public ESheet parent;

    @JsonIgnore
    public EContext getContext() {
        return this.parent.getContext();
    }

    public int id;

    //public Object[] rawValues;

    public void parse(XSSFRowWrap xrw) {
//        int beg = xrw.row.getFirstCellNum();
//        int end = xrw.row.getLastCellNum();
//        rawValues = new Object[end+1];
//        for(int i = beg; i <= end; i++) {
//            XSSFCell cell = xrw.row.getCell(i);
//            if(cell == null) {
//                rawValues[i] = null;
//            } else {
//                String rawValue = XSSFRowWrap.cellString(cell, null);
//                rawValues[i] = rawValue;
//            }
//        }
    }

    /**
     * 注解解析配置表
     */
    public void parseAnno(XSSFRowWrap xrw) {
        try {
            Class<?> clazz = getClass();
            EExcelRowClass annoClazz = clazz.getAnnotation(EExcelRowClass.class);
            if (annoClazz != null) {
                id = xrw.getInteger(annoClazz.IDTitle());
            }
            for (Field field : clazz.getDeclaredFields()) {
                EExcelNoteField noteField = field.getAnnotation(EExcelNoteField.class);
                if (noteField == null) {
                    continue;
                }
                String cellStr = xrw.getString(noteField.fieldName(), noteField.defaultValue());
                if (StringUtils.isEmpty(cellStr)) {
                    cellStr = noteField.defaultValue();
                }
                Object value = null;
                try {
                    value = parseFieldValue(field.getType(), cellStr);
                } catch (Exception e) {
                    parent.getContext().warningOnSheetLoading(parent.parent.getFileName(),
                            parent.getSheetName(),
                            String.format("字段[%s]解析报错! value=[%s] 赋值为缺省值", noteField.fieldName(), cellStr));
                    value = parseDefaultValue(field.getType());
                }
                try {
                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    field.set(this, value);
                } catch (IllegalAccessException e) {
                    log.error("", e);
                }
            }
        } catch (Exception e) {
            log.error("{}", getClass(), e);
        }
    }

    /**
     * 读取单列值
     *
     * @param clazz   值类
     * @param cellStr 配置字串
     */
    private static Object parseFieldValue(Class<?> clazz, String cellStr) {
        if (cellStr == null || cellStr.isEmpty()) {
            return parseDefaultValue(clazz);
        }
        if (String.class.equals(clazz)) {
            return cellStr;
        } else if (int.class.equals(clazz) || Integer.class.equals(clazz)) {
            return Integer.parseInt(cellStr);
        } else if (short.class.equals(clazz) || Short.class.equals(clazz)) {
            return Short.parseShort(cellStr);
        } else if (long.class.equals(clazz) || Long.class.equals(clazz)) {
            return Long.parseLong(cellStr);
        } else if (float.class.equals(clazz) || Float.class.equals(clazz)) {
            return Float.parseFloat(cellStr);
        } else if (byte.class.equals(clazz) || Byte.class.equals(clazz)) {
            return Byte.parseByte(cellStr);
        } else if (double.class.equals(clazz) || Double.class.equals(clazz)) {
            return Double.parseDouble(cellStr);
        } else if (boolean.class.equals(clazz) || Boolean.class.equals(clazz)) {
            if (cellStr.contains("1")) {
                return true;
            }
            return Boolean.parseBoolean(cellStr);
        } else if (Date.class.equals(clazz)) {
            return DateTool.instance().parseOrNull(cellStr);
        } else if (int[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            int[] v_arr = new int[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Integer.parseInt(splits[i]);
            }
            return v_arr;
        } else if (short[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            short[] v_arr = new short[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Short.parseShort(splits[i]);
            }
            return v_arr;
        } else if (long[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            long[] v_arr = new long[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Long.parseLong(splits[i]);
            }
            return v_arr;
        } else if (float[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            float[] v_arr = new float[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Float.parseFloat(splits[i]);
            }
            return v_arr;
        } else if (byte[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            byte[] v_arr = new byte[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Byte.parseByte(splits[i]);
            }
            return v_arr;
        } else if (double[].class.equals(clazz)) {
            String[] splits = cellStr.split("#");
            double[] v_arr = new double[splits.length];
            for (int i = 0; i < splits.length; i++) {
                v_arr[i] = Double.parseDouble(splits[i]);
            }
            return v_arr;
        }
        return null;
    }

    /**
     * 获取默认值
     *
     * @param clazz 值类
     */
    private static Object parseDefaultValue(Class<?> clazz) {
        if (int.class.equals(clazz)) {
            return 0;
        } else if (short.class.equals(clazz)) {
            return (short) 0;
        } else if (long.class.equals(clazz)) {
            return 0L;
        } else if (float.class.equals(clazz)) {
            return 0.0F;
        } else if (byte.class.equals(clazz)) {
            return (byte) 0;
        } else if (double.class.equals(clazz)) {
            return 0.0D;
        } else if (boolean.class.equals(clazz)) {
            return false;
        }
        return null;
    }

    /**
     * 数据是否可用，如果需要添加判断，剔除无效数据，就override这个方法
     */
    public boolean available() {
        return true;
    }

    /**
     * 数据的进一步解析
     */
    public void decode() {
    }

    public String location() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.parent.location());
        sb.append(" ID=" + this.id);
        return sb.toString();
    }

}
